package io.hellsinger.filesystem.linux

object LinuxOperationOptions {
    object Access {
        const val EXISTENCE = 0
        const val EXECUTABLE = 1
        const val WRITABLE = 2
        const val READABLE = 4
    }

    internal object Attributes {
        const val S_IFMT = 61440

        const val S_IFIFO = 4096
        const val S_IFCHR = 8192
        const val S_IFDIR = 16384
        const val S_IFBLK = 24576
        const val S_IFREG = 32768
        const val S_IFLNK = 40960
        const val S_IFSOCK = 49152
    }

    object Permission {
        const val READ_USER = 400
        const val WRITE_USER = 200
        const val EXECUTE_USER = 100

        const val READ_GROUP = 40
        const val WRITE_GROUP = 20
        const val EXECUTE_GROUP = 10

        const val READ_OTHER = 4
        const val WRITE_OTHER = 2
        const val EXECUTE_OTHER = 1
    }

    object Observe {
        const val ACCESS = 1

        // Some files were edited
        const val MODIFY = 2
        const val ATTRIBUTE = 4
        const val CLOSE_WRITING = 8
        const val CLOSE_NO_WRITE = 16
        const val OPEN = 32
        const val MOVE_FROM = 64
        const val MOVE_TO = 128

        // Something was created
        const val CREATE = 256

        // Something was deleted
        const val DELETE = 512
        const val DELETE_SELF = 1024
        const val MOVE_SELF = 2048
        const val UNMOUNT = 8192
        const val OVERFLOW = 16_384
        const val IGNORED = 32_768
        const val CLOSE = CLOSE_WRITING or CLOSE_NO_WRITE
        const val MOVE = MOVE_FROM or MOVE_TO

        const val ONLY_DIR = 16_777_216
        const val DONT_FOLLOW = 33_554_432
        const val EXCL_UNLINK = 67_108_864
        const val MASK_CREATE = 268_435_456
        const val MASK_ADD = 536_870_912

        object Attributes {
            const val DIR = 107_374_1824
        }

        inline val Default
            get() =
                DELETE or
                    CREATE

        const val ALL =
            ACCESS or
                MODIFY or
                ATTRIBUTE or
                CLOSE_WRITING or
                CLOSE_NO_WRITE or
                OPEN or
                MOVE_FROM or
                MOVE_TO or
                DELETE or
                CREATE or
                DELETE_SELF or
                MOVE_SELF

        fun maskToString(mask: Int): String {
            val builder = StringBuilder("(")
            if (mask and ACCESS == ACCESS) builder.append(" Access ")
            if (mask and ATTRIBUTE == ATTRIBUTE) builder.append(" Attribute ")
            if (mask and OPEN == OPEN) builder.append(" Open ")
            if (mask and MOVE_FROM == MOVE_FROM) builder.append(" Move-from ")
            if (mask and MOVE_TO == MOVE_TO) builder.append(" Move-to ")
            if (mask and DELETE == DELETE) builder.append(" Delete ")
            if (mask and CREATE == CREATE) builder.append(" Create ")
            if (mask and DELETE_SELF == DELETE_SELF) builder.append(" Delete-self ")
            if (mask and MOVE_SELF == MOVE_SELF) builder.append(" Move-self ")
            builder.append(")")

            return builder.toString()
        }
    }

    object Open {
        const val READ_ONLY = 0
        const val WRITE_ONLY = 1
        const val READ_AND_WRITE = 2
        const val ASYNC = 32
        const val CREATE_NEW = 64
        const val TRUNCATE = 512
        const val APPEND = 1024
        const val NON_BLOCKING = 2048
        const val CLOSE_ON_EXIT = 524288
        const val PATH = 2097152
    }

    object Copy {
        const val NO_FOLLOW_LINKS = 32
        const val REPLACE_EXISTS = 64

        const val ALL = NO_FOLLOW_LINKS or REPLACE_EXISTS
    }

    object Delete {
        const val NOTIFY_ALL = 128
        const val REMOVE_DIRECTORY = 512

        const val ALL = NOTIFY_ALL
    }

    object Status {
        object System {
            const val READ_ONLY: Long = 0x0001
            const val NO_DEVICE_FILES: Long = 0x0004
            const val NO_EXECUTION: Long = 0x0008
            const val NO_UPDATE_ACCESS_TIME: Long = 0x0400
            const val NO_UPDATE_DIRECTORY_ACCESS_TIME: Long = 0x0800
        }
    }

    const val SCHEME = 0
}
